﻿using System;
using System.Text.Json.Serialization;
using Newtonsoft.Json;
using ThresholdAssistant.DataContract.Extensions;
using ThresholdAssistant.Enums;

namespace ThresholdAssistant.DataContract.Result
{
    /// <summary>
    /// 消费者服务返回值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ConsumerContractResult<T> : ConsumerContractResult
    {
        /// <summary>
        /// 数据
        /// </summary>
        [JsonProperty("data"), JsonPropertyName("data")]
        public T Data { get; set; }

        /// <summary>
        /// 设置成功返回信息
        /// </summary>
        public new ConsumerContractResult<T> SetSuceccful(string serialNo = "")
        {
            Success = true;
            Callback = false;
            if (!string.IsNullOrWhiteSpace(serialNo))
            {
                SerialNo = serialNo;
            }
            ErrorMessage = ErrorTypeEnum.SUCCESS.GetDescription();
            ErrorCode = ErrorTypeEnum.SUCCESS.GetHashCode().ToString();
            return this;
        }

        /// <summary>
        /// 设置成功返回信息
        /// </summary>
        /// <param name="serialNo"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public ConsumerContractResult<T> SetSuceccful(string serialNo = "", T data = default)
        {
            Data = data;
            Success = true;
            Callback = false;
            if (!string.IsNullOrWhiteSpace(serialNo))
            {
                SerialNo = serialNo;
            }
            ErrorMessage = ErrorTypeEnum.SUCCESS.GetDescription();
            ErrorCode = ErrorTypeEnum.SUCCESS.GetHashCode().ToString();
            return this;
        }

        /// <summary>
        /// 设置错误信息
        /// </summary>
        /// <param name="enumType">错误信息</param>
        public new ConsumerContractResult<T> SetError<E>(E enumType) where E : Enum
        {
            Success = false;
            ErrorCode = enumType.GetHashCode().ToString();
            ErrorMessage = enumType.GetDescription();
            return this;
        }

        /// <summary>
        /// 设置错误信息
        /// </summary>
        /// <param name="enumType">错误信息</param>
        /// <param name="serialNo">业务流水号</param>
        /// <param name="merchantNo">商家编号</param>
        /// <param name="extend">透传字段</param>
        public new ConsumerContractResult<T> SetError<E>(E enumType, string serialNo, string merchantNo = default, string extend = default) where E : Enum
        {
            return SetError(enumType.GetHashCode().ToString(), enumType.GetDescription(), serialNo, merchantNo, extend);
        }

        /// <summary>
        /// 设置错误信息
        /// </summary>
        /// <param name="code">错误码</param>
        /// <param name="message">错误消息</param>
        /// <param name="serialNo"></param>
        /// <param name="merchantNo">商家编号</param>
        /// <param name="extend">透传字段</param>
        public new ConsumerContractResult<T> SetError(string code, string message, string serialNo = default, string merchantNo = default, string extend = default)
        {
            Success = false;
            ErrorCode = code;
            Extend = extend;
            ErrorMessage = message;
            MerchantNo = merchantNo;
            if (!string.IsNullOrWhiteSpace(serialNo))
            {
                SerialNo = serialNo;
            }
            return this;
        }

        /// <summary>
        /// 设置成功返回信息
        /// </summary>
        /// <param name="type">回调类型</param>
        /// <param name="data">回调内容</param>
        /// <param name="error">错误类型</param>
        /// <param name="merchantNo">商户编号</param>
        /// <param name="extend">透传字段</param>
        public new ConsumerContractResult<T> SetCallback<EnumType>(Enum type = default, object data = default, EnumType error = default, string merchantNo = default, string extend = default)
            where EnumType : Enum
        {
            return SetCallback(type, data, $"{error.GetHashCode()}", error.GetDescription(), merchantNo, extend);
        }

        /// <summary>
        /// 设置成功返回信息
        /// </summary>
        /// <param name="type">回调类型</param>
        /// <param name="data">回调内容</param>
        /// <param name="code">错误编码</param>
        /// <param name="message">错误消息</param>
        /// <param name="merchantNo">商家编号</param>
        /// <param name="extend">透传字段</param>
        public new ConsumerContractResult<T> SetCallback(Enum type = default, object data = default, string code = default, string message = default, string merchantNo = default, string extend = default)
        {
            Type = type;
            Extend = extend;
            Callback = true;
            if (data != null)
            {
                CallbackData = data;
            }

            if (!string.IsNullOrEmpty(merchantNo))
            {
                MerchantNo = merchantNo;
            }

            if (!string.IsNullOrEmpty(code))
            {
                ErrorCode = code;
            }
            else
            {
                ErrorCode = $"{ErrorTypeEnum.SUCCESS.GetHashCode()}";
            }

            if (!string.IsNullOrEmpty(message))
            {
                ErrorMessage = message;
            }
            else
            {
                ErrorMessage = ErrorTypeEnum.SUCCESS.GetDescription();
            }
            return this;
        }
    }

    /// <summary>
    /// 消费者服务返回值
    /// </summary>
    [Serializable]
    public class ConsumerContractResult : ContractResult
    {
        /// <summary>
        /// 回调类型枚举
        /// </summary>
        [JsonProperty("type"), JsonPropertyName("type")]
        public Enum Type { get; set; }

        /// <summary>
        /// 是否回调商家
        /// </summary>
        [JsonProperty("callback"), JsonPropertyName("callback")]
        public bool Callback { get; set; }

        /// <summary>
        /// 透传字段
        /// </summary>
        [JsonProperty("extend"), JsonPropertyName("extend")]
        public string Extend { get; set; }

        /// <summary>
        /// 商家编号
        /// </summary>
        [JsonProperty("merchant_no"), JsonPropertyName("merchant_no")]
        public string MerchantNo { get; set; }

        /// <summary>
        /// 回调参数
        /// </summary>
        [JsonProperty("callback_data"), JsonPropertyName("callback_data")]
        public object CallbackData { get; set; }

        /// <summary>
        /// 检查是否需要商家回调
        /// </summary>
        public bool IsCallback()
        {
            return Callback || !Success;
        }

        /// <summary>
        /// 检查是否成功
        /// </summary>
        public new bool IsSuceccful()
        {
            return Success;
        }

        /// <summary>
        /// 设置成功返回信息
        /// </summary>
        public new ConsumerContractResult SetSuceccful(string serialNo = "")
        {
            Success = true;
            Callback = false;
            if (!string.IsNullOrWhiteSpace(serialNo))
            {
                SerialNo = serialNo;
            }
            ErrorMessage = ErrorTypeEnum.SUCCESS.GetDescription();
            ErrorCode = ErrorTypeEnum.SUCCESS.GetHashCode().ToString();
            return this;
        }

        /// <summary>
        /// 设置错误信息
        /// </summary>
        /// <param name="enumType">错误信息</param>
        public new ConsumerContractResult SetError<E>(E enumType) where E : Enum
        {
            Success = false;
            ErrorCode = enumType.GetHashCode().ToString();
            ErrorMessage = enumType.GetDescription();
            return this;
        }

        /// <summary>
        /// 设置错误信息
        /// </summary>
        /// <param name="enumType">错误信息</param>
        /// <param name="serialNo">业务流水号</param>
        /// <param name="merchantNo">商家编号</param>
        /// <param name="extend">透传字段</param>
        public ConsumerContractResult SetError<E>(E enumType, string serialNo, string merchantNo = default, string extend = default) where E : Enum
        {
            return SetError(enumType.GetHashCode().ToString(), enumType.GetDescription(), serialNo, merchantNo, extend);
        }

        /// <summary>
        /// 设置错误信息
        /// </summary>
        /// <param name="code">错误码</param>
        /// <param name="message">错误消息</param>
        /// <param name="serialNo"></param>
        /// <param name="merchantNo">商家编号</param>
        /// <param name="extend">透传字段</param>
        public ConsumerContractResult SetError(string code, string message, string serialNo = default, string merchantNo = default, string extend = default)
        {
            Success = false;
            ErrorCode = code;
            Extend = extend;
            ErrorMessage = message;
            MerchantNo = merchantNo;
            if (!string.IsNullOrWhiteSpace(serialNo))
            {
                SerialNo = serialNo;
            }
            return this;
        }

        /// <summary>
        /// 设置成功返回信息
        /// </summary>
        /// <param name="type">回调类型</param>
        /// <param name="data">回调内容</param>
        /// <param name="error">错误类型</param>
        /// <param name="merchantNo">商户编号</param>
        /// <param name="extend">透传字段</param>
        public ConsumerContractResult SetCallback<EnumType>(Enum type = default, object data = default, EnumType error = default, string merchantNo = default, string extend = default)
            where EnumType : Enum
        {
            return SetCallback(type, data, $"{error.GetHashCode()}", error.GetDescription(), merchantNo, extend);
        }

        /// <summary>
        /// 设置成功返回信息
        /// </summary>
        /// <param name="type">回调类型</param>
        /// <param name="data">回调内容</param>
        /// <param name="code">错误编码</param>
        /// <param name="message">错误消息</param>
        /// <param name="merchantNo">商家编号</param>
        /// <param name="extend">透传字段</param>
        public ConsumerContractResult SetCallback(Enum type = default, object data = default, string code = default, string message = default, string merchantNo = default, string extend = default)
        {
            Type = type;
            Extend = extend;
            Callback = true;
            if (data != null)
            {
                CallbackData = data;
            }

            if (!string.IsNullOrEmpty(merchantNo))
            {
                MerchantNo = merchantNo;
            }

            if (!string.IsNullOrEmpty(code))
            {
                ErrorCode = code;
            }
            else
            {
                ErrorCode = $"{ErrorTypeEnum.SUCCESS.GetHashCode()}";
            }

            if (!string.IsNullOrEmpty(message))
            {
                ErrorMessage = message;
            }
            else
            {
                ErrorMessage = ErrorTypeEnum.SUCCESS.GetDescription();
            }
            return this;
        }
    }
}